Skip to content

feat: add guided tour#3051

Open
yashmehrotra wants to merge 6 commits into
mainfrom
tour
Open

feat: add guided tour#3051
yashmehrotra wants to merge 6 commits into
mainfrom
tour

Conversation

@yashmehrotra

@yashmehrotra yashmehrotra commented Jun 22, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

Release Notes

  • New Features
    • Added a “Getting started” checklist page and route, including a “Take a guided tour” entry.
    • Introduced a guided tour experience with a “Take a tour” menu, route/target-based step progression, and a custom tooltip.
    • Record progress via guided-tour touchpoints from key actions, navigation, and observers; added touchpoint APIs.
  • Bug Fixes
    • Improved flow error handling robustness for partially missing error payload fields.
  • Tests
    • Added unit tests covering guided tour step construction and progression.
  • Refactor
    • Updated VersionInfo to support ref forwarding.

@vercel

vercel Bot commented Jun 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
aws-preview Ready Ready Preview Jun 29, 2026 5:28am
flanksource-ui Ready Ready Preview Jun 29, 2026 5:28am

Request Review

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 41ec93c2-fda0-49fa-8324-f6b64cd307a6

📥 Commits

Reviewing files that changed from the base of the PR and between 5444bf9 and 7e59736.

📒 Files selected for processing (1)
  • src/components/GuidedTour/touchpoints.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/GuidedTour/touchpoints.ts

Walkthrough

Adds a guided tour with Joyride, touchpoint tracking, a Getting Started page, route wiring, and tour markers across the UI. Also updates Kratos error handling to use optional chaining for nested redirect fields.

Changes

Guided Tour Feature

Layer / File(s) Summary
Tour contracts and step modules
package.json, src/api/services/touchpoints.ts, src/components/GuidedTour/steps/*, src/components/GuidedTour/touchpoints.ts, src/components/GuidedTour/useTouchpoints.ts
Adds Joyride, touchpoint storage helpers, shared step metadata and target finders, checklist touchpoint catalogs, and per-section step arrays.
Tour state, assembly, and validation
src/components/GuidedTour/guidedTourState.ts, src/components/GuidedTour/guidedTourSteps.ts, src/components/GuidedTour/__tests__/guidedTourSteps.unit.test.ts
Defines the tour atoms and hooks, assembles full and section tours, computes touchpoint step chains, handles Joyride progression and missing-target cases, and validates the step logic in tests.
Tour runtime and entry points
src/components/GuidedTour/GuidedTour.tsx, src/components/GuidedTour/TourMenu.tsx, src/components/GuidedTour/TourTooltip.tsx, src/components/GuidedTour/TouchpointObserver.tsx, src/ui/Layout/SidebarLayout.tsx, src/App.tsx, src/components/Users/UserProfile.tsx, src/components/Authentication/Kratos/KratosUserProfileDropdown.tsx, src/components/VersionInfo/VersionInfo.tsx
Implements the Joyride runtime, section picker modal, custom tooltip, route-based touchpoint observer, sidebar mounting, the getting-started route, profile menu launch actions, and ref forwarding on version info.
Tour target instrumentation
src/components/Layout/AppSidebar.tsx, src/ui/Tabs/TabbedLinks.tsx, src/ui/Buttons/DialogButton.tsx, src/components/Canary/..., src/components/Configs/..., src/components/Playbooks/..., src/pages/...
Adds data-tour markers and related attributes to sidebar links, tabs, buttons, canary views, config and playbook surfaces, and page wrappers used by guided-tour targeting.

Kratos Error Handler Fix

Layer / File(s) Summary
Optional chaining in handleGetFlowError
src/components/Authentication/Kratos/ory/hooks.ts
Changes the Kratos error-id switch and redirect assignments to read nested error and redirect fields with optional chaining.

Possibly related PRs

Suggested reviewers

  • moshloop
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 46.15% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding a guided tour feature.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch tour
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch tour

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@socket-security

socket-security Bot commented Jun 22, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedreact-joyride@​3.1.0991009986100

View full report

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/components/GuidedTour/__tests__/guidedTourSteps.unit.test.ts (1)

27-50: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add regression tests for empty-param gating and PREV-at-zero behavior.

These two boundaries are currently untested and are easy to regress in the pure reducers.

Suggested test additions
 describe("resolveAutoAdvance", () => {
@@
   it("does not advance when the gated param is absent", () => {
     expect(resolveAutoAdvance(steps, 2, ctx("/health"))).toBeNull();
   });
+
+  it("does not advance when the gated param is present but empty", () => {
+    expect(resolveAutoAdvance(steps, 2, ctx("/health", "checkId="))).toBeNull();
+  });
@@
 describe("reduceTourEvent", () => {
@@
   it("goes back on a prev-button step:after event", () => {
     expect(reduceTourEvent({ ...base, action: ACTIONS.PREV })).toEqual({
       run: true,
       stepIndex: 0
     });
   });
+
+  it("does not go below zero on prev from the first step", () => {
+    expect(
+      reduceTourEvent({ ...base, action: ACTIONS.PREV, index: 0 })
+    ).toEqual({
+      run: true,
+      stepIndex: 0
+    });
+  });

Also applies to: 152-194

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/GuidedTour/__tests__/guidedTourSteps.unit.test.ts` around
lines 27 - 50, Add two new test cases to the resolveAutoAdvance test suite.
First, add a test that verifies the behavior when a parameter is present but
empty (like "checkId=" with no value) to cover empty-param gating scenarios.
Second, add a test that verifies what happens when attempting to navigate to the
previous step (using PREV) when currently at step index 0, which is a boundary
condition that should be tested. These tests should follow the same pattern as
the existing tests in the suite and use the ctx() helper function with
appropriate parameters.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/Authentication/Kratos/ory/hooks.ts`:
- Line 54: The code assigns err.response?.data?.redirect_browser_to directly to
window.location.href without verifying that redirect_browser_to is actually
defined. If Kratos returns an incomplete response where redirect_browser_to is
undefined, this will cause uncontrolled navigation. Add a guard condition to
check if redirect_browser_to exists before assigning it to window.location.href,
and implement a controlled fallback behavior (such as redirecting to a safe
route or resetting the state) when it is undefined. This same fix needs to be
applied to both instances mentioned (line 54 and line 85).

In `@src/components/GuidedTour/guidedTourSteps.ts`:
- Around line 588-590: The PREV action handler does not guard against
decrementing the step index below zero, which occurs when at index 0. Add a
guard condition in the block where action === ACTIONS.PREV to check if index is
greater than 0 before returning the decremented stepIndex. If the index is
already at 0, either return the current state unchanged or handle it
appropriately to prevent the invalid negative index that causes tour state
desyncing.
- Around line 522-523: The paramPresent variable in guidedTourSteps.ts currently
checks if the query parameter is non-null, but URLSearchParams.get() returns an
empty string for parameters like ?param=, which passes the null check and
incorrectly advances the tour. Modify the condition to also verify that the
parameter value is not an empty string, so only parameters with actual non-empty
values are treated as present for the auto-advance gate logic.

---

Nitpick comments:
In `@src/components/GuidedTour/__tests__/guidedTourSteps.unit.test.ts`:
- Around line 27-50: Add two new test cases to the resolveAutoAdvance test
suite. First, add a test that verifies the behavior when a parameter is present
but empty (like "checkId=" with no value) to cover empty-param gating scenarios.
Second, add a test that verifies what happens when attempting to navigate to the
previous step (using PREV) when currently at step index 0, which is a boundary
condition that should be tested. These tests should follow the same pattern as
the existing tests in the suite and use the ctx() helper function with
appropriate parameters.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 486ff875-9f0b-40c4-8be0-e4ef5ead1b0e

📥 Commits

Reviewing files that changed from the base of the PR and between 964cda8 and 509e6b3.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (30)
  • package.json
  • src/components/Authentication/Kratos/KratosUserProfileDropdown.tsx
  • src/components/Authentication/Kratos/ory/hooks.ts
  • src/components/Canary/CanaryPopup/CheckDetails.tsx
  • src/components/Canary/CanaryPopup/CheckDetailsTabs.tsx
  • src/components/Canary/CanaryPopup/CheckRunNow.tsx
  • src/components/Canary/CanaryTable.tsx
  • src/components/Canary/index.tsx
  • src/components/Configs/ConfigList/MRTConfigListColumn.tsx
  • src/components/Configs/ConfigSummary/Cells/ConfigSummaryTableVirtualAggregateColumn.tsx
  • src/components/Configs/ConfigSummary/ConfigSummaryList.tsx
  • src/components/GuidedTour/GuidedTour.tsx
  • src/components/GuidedTour/TourMenu.tsx
  • src/components/GuidedTour/TourTooltip.tsx
  • src/components/GuidedTour/__tests__/guidedTourSteps.unit.test.ts
  • src/components/GuidedTour/guidedTourState.ts
  • src/components/GuidedTour/guidedTourSteps.ts
  • src/components/Layout/AppSidebar.tsx
  • src/components/Playbooks/Runs/PlaybookRunsList.tsx
  • src/components/Playbooks/Runs/Submit/SubmitPlaybookRunForm.tsx
  • src/components/Playbooks/Settings/PlaybookSpecCard.tsx
  • src/components/Users/UserProfile.tsx
  • src/components/VersionInfo/VersionInfo.tsx
  • src/pages/config/ConfigList.tsx
  • src/pages/config/details/ConfigDetailsPage.tsx
  • src/pages/playbooks/PlaybookRunsDetails.tsx
  • src/pages/views/components/ViewContainer.tsx
  • src/ui/Buttons/DialogButton.tsx
  • src/ui/Layout/SidebarLayout.tsx
  • src/ui/Tabs/TabbedLinks.tsx

case "session_refresh_required":
// We need to re-authenticate to perform this action
window.location.href = err.response?.data.redirect_browser_to;
window.location.href = err.response?.data?.redirect_browser_to;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Guard redirect_browser_to before assigning window.location.href

Both branches now allow undefined to flow into window.location.href. If Kratos returns a partial payload, this can trigger incorrect navigation rather than a controlled fallback. Add a null check (and fallback route/reset) before redirecting.

Suggested fix
       case "session_refresh_required":
         // We need to re-authenticate to perform this action
-        window.location.href = err.response?.data?.redirect_browser_to;
+        if (err.response?.data?.redirect_browser_to) {
+          window.location.href = err.response.data.redirect_browser_to;
+          return;
+        }
+        resetFlow(undefined);
+        await router.push("/" + flowType);
         return;
@@
       case "browser_location_change_required":
         // Ory Kratos asked us to point the user to this URL.
-        window.location.href = err.response?.data?.redirect_browser_to;
+        if (err.response?.data?.redirect_browser_to) {
+          window.location.href = err.response.data.redirect_browser_to;
+          return;
+        }
+        resetFlow(undefined);
+        await router.push("/" + flowType);
         return;

Also applies to: 85-85

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/Authentication/Kratos/ory/hooks.ts` at line 54, The code
assigns err.response?.data?.redirect_browser_to directly to window.location.href
without verifying that redirect_browser_to is actually defined. If Kratos
returns an incomplete response where redirect_browser_to is undefined, this will
cause uncontrolled navigation. Add a guard condition to check if
redirect_browser_to exists before assigning it to window.location.href, and
implement a controlled fallback behavior (such as redirecting to a safe route or
resetting the state) when it is undefined. This same fix needs to be applied to
both instances mentioned (line 54 and line 85).

Comment on lines +522 to +523
const paramPresent =
!!data.advanceOnParam && ctx.params.get(data.advanceOnParam) != null;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Treat empty query-param values as absent for auto-advance gates.

URLSearchParams.get() returns "" for ?param=, and the current condition advances on that. This can skip gated steps before a real selection exists.

Suggested fix
-  const paramPresent =
-    !!data.advanceOnParam && ctx.params.get(data.advanceOnParam) != null;
+  const paramValue = data.advanceOnParam
+    ? ctx.params.get(data.advanceOnParam)
+    : null;
+  const paramPresent = paramValue != null && paramValue !== "";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const paramPresent =
!!data.advanceOnParam && ctx.params.get(data.advanceOnParam) != null;
const paramValue = data.advanceOnParam
? ctx.params.get(data.advanceOnParam)
: null;
const paramPresent = paramValue != null && paramValue !== "";
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/GuidedTour/guidedTourSteps.ts` around lines 522 - 523, The
paramPresent variable in guidedTourSteps.ts currently checks if the query
parameter is non-null, but URLSearchParams.get() returns an empty string for
parameters like ?param=, which passes the null check and incorrectly advances
the tour. Modify the condition to also verify that the parameter value is not an
empty string, so only parameters with actual non-empty values are treated as
present for the auto-advance gate logic.

Comment on lines +588 to +590
if (action === ACTIONS.PREV) {
return { run: true, stepIndex: index - 1 };
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Guard PREV transitions from producing a negative step index.

A PREV event at index 0 currently returns -1, which is an invalid controlled index and can desync tour state.

Suggested fix
    if (action === ACTIONS.PREV) {
-      return { run: true, stepIndex: index - 1 };
+      return { run: true, stepIndex: Math.max(0, index - 1) };
    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (action === ACTIONS.PREV) {
return { run: true, stepIndex: index - 1 };
}
if (action === ACTIONS.PREV) {
return { run: true, stepIndex: Math.max(0, index - 1) };
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/GuidedTour/guidedTourSteps.ts` around lines 588 - 590, The
PREV action handler does not guard against decrementing the step index below
zero, which occurs when at index 0. Add a guard condition in the block where
action === ACTIONS.PREV to check if index is greater than 0 before returning the
decremented stepIndex. If the index is already at 0, either return the current
state unchanged or handle it appropriately to prevent the invalid negative index
that causes tour state desyncing.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/GuidedTour/GuidedTour.tsx`:
- Around line 109-118: The visibility check using `offsetParent === null` in the
GuidedTour component incorrectly identifies fixed-position elements as hidden,
causing tour targets in the AppSidebar (which uses position: fixed) to be
skipped. Replace this visibility check with a more robust approach that
tolerates fixed positioning by using getBoundingClientRect() to verify the
element has visible dimensions, or alternatively use getClientRects().length to
confirm the element renders. This will ensure fixed-position tour targets are
correctly identified as visible and clickable rather than being incorrectly
skipped.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a2dfcf41-26d9-464b-9cbd-2f2a345aae5d

📥 Commits

Reviewing files that changed from the base of the PR and between 509e6b3 and 41b42fd.

📒 Files selected for processing (3)
  • src/components/GuidedTour/GuidedTour.tsx
  • src/components/GuidedTour/TourMenu.tsx
  • src/components/GuidedTour/guidedTourSteps.ts
✅ Files skipped from review due to trivial changes (1)
  • src/components/GuidedTour/guidedTourSteps.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/GuidedTour/TourMenu.tsx

Comment on lines +109 to +118
if (element) {
// Present but hidden (e.g. the Graph tab on tall viewports) can never
// be clicked — skip now rather than waiting it out.
if (element.offsetParent === null) {
skip();
return;
}
attached = element;
element.addEventListener("click", onClick, { once: true });
return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect the data-tour targets and their containers to see if any are position:fixed.
rg -n 'data-tour' src --type=tsx --type=ts -C1 | head -n 80

Repository: flanksource/flanksource-ui

Length of output: 192


🏁 Script executed:

# Find data-tour attributes in tsx/ts files without type filter
rg 'data-tour' src --type ts -C 1 | head -100

Repository: flanksource/flanksource-ui

Length of output: 7141


🏁 Script executed:

# Inspect the GuidedTour.tsx file to understand the context better
ast-grep outline src/components/GuidedTour/GuidedTour.tsx

Repository: flanksource/flanksource-ui

Length of output: 374


🏁 Script executed:

# Search for any CSS or inline styles that set position:fixed in relation to tour elements
rg 'position.*fixed' src --type ts --type js -C 2 | head -100

Repository: flanksource/flanksource-ui

Length of output: 3291


🏁 Script executed:

# Read GuidedTour.tsx around lines 109-118 to see the full context
sed -n '100,130p' src/components/GuidedTour/GuidedTour.tsx

Repository: flanksource/flanksource-ui

Length of output: 1037


🏁 Script executed:

# Check AppSidebar styling and positioning
grep -n 'className\|style\|position' src/components/Layout/AppSidebar.tsx | head -40

Repository: flanksource/flanksource-ui

Length of output: 1583


🏁 Script executed:

# Search for CSS classes or Tailwind utilities that might apply position:fixed to AppSidebar
rg 'fixed|sticky' src/components/Layout/AppSidebar.tsx -B2 -A2

Repository: flanksource/flanksource-ui

Length of output: 164


🏁 Script executed:

# View the full AppSidebar component to understand its structure
cat -n src/components/Layout/AppSidebar.tsx | head -100

Repository: flanksource/flanksource-ui

Length of output: 3828


🏁 Script executed:

# Check what Sidebar component is being used and if it has fixed positioning
rg 'from.*Sidebar|import.*Sidebar' src/components/Layout/AppSidebar.tsx -A5

Repository: flanksource/flanksource-ui

Length of output: 164


🏁 Script executed:

# Check the Layout or main app structure to see if AppSidebar is positioned fixed
rg -l 'AppSidebar' src --type ts --type tsx | xargs grep -l 'fixed\|sticky\|position' | head -5

Repository: flanksource/flanksource-ui

Length of output: 192


🏁 Script executed:

# Find the sidebar component file
find src -name 'sidebar*' -type f

Repository: flanksource/flanksource-ui

Length of output: 246


🏁 Script executed:

# Check the sidebar component for positioning styles
cat src/components/ui/sidebar.tsx | head -150

Repository: flanksource/flanksource-ui

Length of output: 4669


🏁 Script executed:

# Search for position styling in the sidebar component
grep -n 'position\|fixed\|sticky' src/components/ui/sidebar.tsx

Repository: flanksource/flanksource-ui

Length of output: 300


offsetParent === null misclassifies fixed-position targets as hidden.

The Sidebar component (used by AppSidebar) applies position: fixed via the CSS class "fixed" (sidebar.tsx:245). Since AppSidebar contains elements with data-tour attributes for navigation targets, these tour targets would have offsetParent === null despite being fully visible and clickable. The check at lines 109–118 would incorrectly skip() these targets. Consider a visibility check that tolerates fixed positioning (e.g. getBoundingClientRect() dimensions or getClientRects().length).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/GuidedTour/GuidedTour.tsx` around lines 109 - 118, The
visibility check using `offsetParent === null` in the GuidedTour component
incorrectly identifies fixed-position elements as hidden, causing tour targets
in the AppSidebar (which uses position: fixed) to be skipped. Replace this
visibility check with a more robust approach that tolerates fixed positioning by
using getBoundingClientRect() to verify the element has visible dimensions, or
alternatively use getClientRects().length to confirm the element renders. This
will ensure fixed-position tour targets are correctly identified as visible and
clickable rather than being incorrectly skipped.

}
];

const healthSteps: Step[] = [

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Tour file per "guide"
  • Use onboarding checklist (like storybook) - with floating panel (minimizable / dismissisable to localstorage) and Menu -> Getting Started link
  • Split tours into Admin vs Operator and then by category

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/Canary/CanaryPopup/CheckRunNow.tsx`:
- Around line 56-58: The touchpoint for health.run-now is being recorded too
early in CheckRunNow’s onClick handler, before runNow(check.id) succeeds. Move
recordTouchpoint("health.run-now") into the successful completion path of the
runNow mutation/callback for CheckRunNow so the action is only marked after a
successful run, and keep the existing onClick and runNow(check.id) flow
otherwise unchanged.

In `@src/components/GuidedTour/steps/views.ts`:
- Line 4: The “Views” opener currently falls back to the dashboard via
findViewTarget, so the tour step can highlight the wrong element instead of
skipping. Update the lookup logic in findViewTarget (and the Views step that
uses tourTarget/TourStepData) to stop returning the dashboard as a fallback for
the views opener, so onMissing: "skipSection" can trigger when no real views
entrypoint exists. Keep the target selection specific to the views entrypoint
and leave dashboard fallback only for contexts that explicitly need it.

In `@src/components/Playbooks/Runs/Submit/SubmitPlaybookRunForm.tsx`:
- Around line 113-115: Move the playbooks.run touchpoint recording in
SubmitPlaybookRunForm so it happens only after submitPlaybookRun succeeds
instead of before the async call. Update the onSubmit handler to await/handle
the result from submitPlaybookRun(values as SubmitPlaybookRunFormValues) and
call recordTouchpoint("playbooks.run") only on success, keeping the change
localized to SubmitPlaybookRunForm and its onSubmit flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9b0e7d2a-2140-488c-ac59-fe206df064cd

📥 Commits

Reviewing files that changed from the base of the PR and between 41b42fd and 5444bf9.

📒 Files selected for processing (23)
  • src/App.tsx
  • src/api/services/touchpoints.ts
  • src/components/Authentication/Kratos/KratosUserProfileDropdown.tsx
  • src/components/Canary/CanaryPopup/CheckDetails.tsx
  • src/components/Canary/CanaryPopup/CheckRunNow.tsx
  • src/components/Configs/ConfigDetailsTabs.tsx
  • src/components/GuidedTour/TouchpointObserver.tsx
  • src/components/GuidedTour/TourMenu.tsx
  • src/components/GuidedTour/__tests__/guidedTourSteps.unit.test.ts
  • src/components/GuidedTour/guidedTourState.ts
  • src/components/GuidedTour/guidedTourSteps.ts
  • src/components/GuidedTour/steps/catalog.ts
  • src/components/GuidedTour/steps/dashboard.ts
  • src/components/GuidedTour/steps/health.ts
  • src/components/GuidedTour/steps/playbooks.ts
  • src/components/GuidedTour/steps/shared.ts
  • src/components/GuidedTour/steps/views.ts
  • src/components/GuidedTour/touchpoints.ts
  • src/components/GuidedTour/useTouchpoints.ts
  • src/components/Playbooks/Runs/Submit/SubmitPlaybookRunForm.tsx
  • src/components/Users/UserProfile.tsx
  • src/pages/GettingStartedPage.tsx
  • src/ui/Layout/SidebarLayout.tsx
✅ Files skipped from review due to trivial changes (2)
  • src/components/GuidedTour/steps/playbooks.ts
  • src/components/GuidedTour/touchpoints.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/ui/Layout/SidebarLayout.tsx
  • src/components/GuidedTour/guidedTourState.ts
  • src/components/Canary/CanaryPopup/CheckDetails.tsx
  • src/components/GuidedTour/TourMenu.tsx

Comment on lines 56 to 58
onClick={() => {
recordTouchpoint("health.run-now");
runNow(check.id);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Move touchpoint recording into the mutation success path.

Line 57 records health.run-now before runNow(check.id) completes. If the request fails, the checklist still shows the action as completed even though no successful run happened.

Proposed fix
   const { isLoading, mutate: runNow } = useMutation({
     mutationFn: runHealthCheckNow,
     onSuccess: (data) => {
+      recordTouchpoint("health.run-now");
       onSuccessfulRun(data.data);
     }
   });
@@
         onClick={() => {
-          recordTouchpoint("health.run-now");
           runNow(check.id);
         }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onClick={() => {
recordTouchpoint("health.run-now");
runNow(check.id);
onClick={() => {
runNow(check.id);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/Canary/CanaryPopup/CheckRunNow.tsx` around lines 56 - 58, The
touchpoint for health.run-now is being recorded too early in CheckRunNow’s
onClick handler, before runNow(check.id) succeeds. Move
recordTouchpoint("health.run-now") into the successful completion path of the
runNow mutation/callback for CheckRunNow so the action is only marked after a
successful run, and keep the existing onClick and runNow(check.id) flow
otherwise unchanged.

// ABOUTME: The views section of the guided tour and its checklist touchpoint.
// ABOUTME: Opens a custom view and explains that views compose graphs, tables and charts.
import { type Step } from "react-joyride";
import { findViewTarget, tourTarget, type TourStepData } from "./shared";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Stop falling back to the dashboard for the “Views” opener.

onMissing: "skipSection" cannot fire here because findViewTarget in src/components/GuidedTour/steps/shared.ts:130-138 falls back to [data-tour="dashboard"]. When no real views entrypoint is rendered, this step highlights Dashboard, asks the user to open a view, and advances on the wrong click instead of skipping the section.

Suggested fix
-import { findViewTarget, tourTarget, type TourStepData } from "./shared";
+import { tourTarget, type TourStepData } from "./shared";
@@
-    target: findViewTarget,
+    target: () =>
+      document.querySelector<HTMLElement>(
+        '[data-tour="views"][data-tour-name="system"]'
+      ) ?? document.querySelector<HTMLElement>('[data-tour="views"]'),

Also applies to: 8-21

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/GuidedTour/steps/views.ts` at line 4, The “Views” opener
currently falls back to the dashboard via findViewTarget, so the tour step can
highlight the wrong element instead of skipping. Update the lookup logic in
findViewTarget (and the Views step that uses tourTarget/TourStepData) to stop
returning the dashboard as a fallback for the views opener, so onMissing:
"skipSection" can trigger when no real views entrypoint exists. Keep the target
selection specific to the views entrypoint and leave dashboard fallback only for
contexts that explicitly need it.

Comment on lines 113 to 115
onSubmit={(values) => {
recordTouchpoint("playbooks.run");
submitPlaybookRun(values as SubmitPlaybookRunFormValues);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Record the touchpoint only after the run succeeds.

Line 114 marks playbooks.run complete before submitPlaybookRun resolves. Any validation, permission, or network failure will still persist the checklist item as done, so the guided-tour state can diverge from the actual outcome.

Proposed fix
   const { mutate: submitPlaybookRun, isLoading } = useSubmitPlaybookRunMutation(
     {
       onSuccess: (run) => {
+        recordTouchpoint("playbooks.run");
         navigate(`/playbooks/runs/${run.run_id}`);
       },
       onError: (error) => {
         const message =
           ((error as AxiosError).response?.data as any)?.error ?? error.message;
@@
         initialValues={initialValues}
         validateOnMount
         onSubmit={(values) => {
-          recordTouchpoint("playbooks.run");
           submitPlaybookRun(values as SubmitPlaybookRunFormValues);
         }}
       >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onSubmit={(values) => {
recordTouchpoint("playbooks.run");
submitPlaybookRun(values as SubmitPlaybookRunFormValues);
onSubmit={(values) => {
submitPlaybookRun(values as SubmitPlaybookRunFormValues);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/Playbooks/Runs/Submit/SubmitPlaybookRunForm.tsx` around lines
113 - 115, Move the playbooks.run touchpoint recording in SubmitPlaybookRunForm
so it happens only after submitPlaybookRun succeeds instead of before the async
call. Update the onSubmit handler to await/handle the result from
submitPlaybookRun(values as SubmitPlaybookRunFormValues) and call
recordTouchpoint("playbooks.run") only on success, keeping the change localized
to SubmitPlaybookRunForm and its onSubmit flow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants